package com.c503.sc.mytest.common.controller;

import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MaxUploadSizeExceededException;

import com.alibaba.fastjson.JSON;
import com.c503.sc.base.common.NumberContant;
import com.c503.sc.base.exception.CustomException;
import com.c503.sc.log.ControlLogModel;
import com.c503.sc.log.LoggingManager;
import com.c503.sc.mytest.common.constant.CacheConstant;
import com.c503.sc.mytest.common.model.BizUserEntity;
import com.c503.sc.mytest.common.utils.CacheManagerFactory;
import com.c503.sc.utils.basetools.C503StringUtils;
import com.c503.sc.utils.cache.CacheManager;
import com.c503.sc.utils.cache.ICache;
import com.c503.sc.utils.response.ResultMessage;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * 〈一句话功能简述〉 控制层基类，定义一些共有的方法，也可以是抽象方法，在各个子类中具体实现 〈功能详细描述〉
 * 
 * @author liuj
 * @version [版本号, 2018年1月7日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 *
 */

public abstract class BaseController {
	
	 /** 缓存管理器 */
    private static final CacheManager MANAGER =
        CacheManagerFactory.getInstence().getCacheManager();
    
	/** 错误验证消息集合 */
    private Map<String, Object> validErorrs = new HashMap<String, Object>();
   
    /**
     * 〈一句话功能简述〉获得错误信息集合 〈功能详细描述〉
     * 
     * @return 错误信息集合
     * @see [类、类#方法、类#成员]
     */
    public Map<String, Object> getValidErorrs() {
        return validErorrs;
    }
    
    /**
     * 〈一句话功能简述〉设置错误信息集合 〈功能详细描述〉
     * 
     * @param validErorrs
     *            错误信息集合
     * @see [类、类#方法、类#成员]
     */
    public void setValidErorrs(Map<String, Object> validErorrs) {
        this.validErorrs = validErorrs;
    }
    
    
    /**
     * 〈一句话功能简述〉 从缓存中获得用户信息 〈功能详细描述〉
     * 
     * @return 用户信息
     * @throws Exception
     *             系统异常
     * @see [类、类#方法、类#成员]
     */
    public BizUserEntity getUser()
        throws Exception {
        ICache<String, BizUserEntity> cache =
            MANAGER.getCache(CacheConstant.CACHE_LOGIN_USER);
        BizUserEntity user = cache.get(getToken());
        return user;
    }
    
    /**
     * 〈一句话功能简述〉全局异常处理 〈功能详细描述〉
     * 
     * @param request 请求
     * @param response 响应
     * @param e 异常
     * @return 消息体
     * @see [类、类#方法、类#成员]
     */
    @SuppressWarnings("deprecation")
    @ExceptionHandler()
    public String exception(HttpServletRequest request,
        HttpServletResponse response, Exception e) {
        // 这里进行通用处理，如日志记录等...
        logger().error(0, e);
        // 文件过大异常
        if (e instanceof MaxUploadSizeExceededException) {
            return "error";
        }
        // 导出模板报错
       /* if (e instanceof TemplateException) {
            return "error";
        }*/
        // 如果是json格式的ajax请求
        String accept = request.getHeader("accept");
        String xRequestedWith = request.getHeader("X-Requested-With");
        if (accept.indexOf("application/json") > -1
            || accept.indexOf("text/html") > -1
            || (xRequestedWith != null && xRequestedWith.indexOf("XMLHttpRequest") > -1)) {
            // response.setStatus(500);
            response.setContentType("application/json;charset=utf-8");
            JsonGenerator jsonGenerator = null;
            OutputStream out = null;
            
            ResultMessage message = new ResultMessage();
            try {
                // 默认异常信息委系统内部错误
                String errorMsg = "Internal system error.";
                int exceptCode = NumberContant.THREE;
                if (e instanceof CustomException) {
                    
                    CustomException baseException = (CustomException) e;
                    errorMsg = baseException.getErrorMessage();
                    message.setCode(Integer.valueOf(String.valueOf(baseException.getErrorId())
                        .substring(0, 1)));
                    exceptCode = (int) baseException.getErrorId();
                }
                controlErrorLog(ControlLogModel.CONTROL_RESULT_FAIL,
                    exceptCode,
                    errorMsg).recordLog();
                
                message.setMsg(errorMsg);
                
                out = response.getOutputStream();
                ObjectMapper mapper = new ObjectMapper();
                jsonGenerator =
                    mapper.getJsonFactory().createJsonGenerator(out,
                        JsonEncoding.UTF8);
                jsonGenerator.writeObject(message);
                jsonGenerator.flush();
            }
            catch (Exception e1) {
                logger().error(0, new CustomException(0, e1));
            }
            finally {
                if (jsonGenerator != null) {
                    try {
                        jsonGenerator.close();
                    }
                    catch (IOException e1) {
                        logger().error(0, e1);
                    }
                }
                
                if (out != null) {
                    try {
                        out.close();
                    }
                    catch (IOException e1) {
                        logger().error(0, e1);
                    }
                }
            }
            logger().info(0);
            
            return null;
        }
        else {
            // 如果是普通请求
            request.setAttribute("exceptionMessage", e.getMessage());
            
            logger().info(0);
            // 根据不同的异常类型可以返回不同界面
            return "error";
        }
    }

    /**
     * 〈一句话功能简述〉获取子类日志管理对象 〈功能详细描述〉
     * 
     * @return 日志管理对象
     * @see [类、类#方法、类#成员]
     */
    protected abstract LoggingManager logger();
    
    /**
     * 
     * 〈一句话功能简述〉记录操作日志 〈功能详细描述〉
     * 
     * @param resultCode 是否操作成功
     * @param msgCode 消息码
     * @param args 消息码参数
     * @return 操作日志对象
     * @throws Exception 系统异常
     * @see [类、类#方法、类#成员]
     */
    protected ControlLogModel controlErrorLog(int resultCode, int msgCode,
        Object... args)
        throws Exception {
        BizUserEntity user = getUser();
        String msg = JSON.toJSONString(args);
        ControlLogModel log =
            new ControlLogModel(null, user.getName(), resultCode, logger());
        log.setControlMessage(msg);
        return log;
    }
        
    /**
     * 〈一句话功能简述〉获取token 后期用filter拦截器实现 〈功能详细描述〉
     * 
     * @return 响应消息
     * @see [类、类#方法、类#成员]
     */
    public static String getToken() {
        String token = null;
        // 退出之前或跳转之前先获取cookie 后续用filter拦截器实现
        Cookie[] cookies =
            getRequest() == null ? null : getRequest().getCookies();
        if (null != cookies) {
            String tokenName =
                com.c503.sc.base.common.CommonConstants.COOKIE_TOKEN;
            for (Cookie cookie : cookies) {
                if (C503StringUtils.equals(tokenName, cookie.getName())) {
                    token = cookie.getValue();
                    break;
                }
            }
        }
        return token;
    }
    
    /**
     * 〈一句话功能简述〉得到request对象 〈功能详细描述〉
     * 
     * @return request对象
     * @see [类、类#方法、类#成员]
     */
    protected static HttpServletRequest getRequest() {
        ServletRequestAttributes servletRequestAttributes =
            (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = null;
        if (null != servletRequestAttributes) {
            request = servletRequestAttributes.getRequest();
        }
        return request;
    }

}
